Object-oriented Programming Languages Need Well-founded Contracts
نویسندگان
چکیده
Over the past few years, the notion of building software from components has become popular again. The goal is to produce systems by adapting and linking off-the-shelf modules from a pool of interchangeable components. To turn this idea into reality, the formal descriptions of software components need to specify more than the type signatures of their exported services. At a minimum, they should contain assertions about critical properties of a component’s behavior. By monitoring such behavioral contracts at run-time, language implementations can pinpoint faulty components, and programmers can replace them with different ones. In this paper, we study the notion of behavioral contracts in an object-oriented setting. While the use of behavioral contracts is well-understood in the world of procedural languages, their addition to object-oriented programming languages poses remarkably subtle problems. All existing contract enforcement tools for Java fail to catch flaws in contracts or blame the wrong component for contractual violations. The failures point to a lack of foundational research on behavioral contracts in the OOP world. 1 Components, Contracts, and Classes In 1969, McIlroy [16] proposed the idea of reusable software components. In a market place with reusable components, software manufacturers produce interchangeable software components with well-specified interfaces. Programmers assemble systems from these off-the-shelf components, possibly adapting some with wrapper code or adding a few new ones. When a component fails to live up to its promises, a programmer replaces it with a different one. When a manufacturer improves a component, the programmer can improve the final product by replacing the link to the old component with a link to the new one. To make this component market work, component interfaces should state more than the type signatures of exported and imported items. Ideally, interfaces should specify the entire behavior of a component; realistically, interfaces should at least specify essential aspects of the behavior. The earliest suggestion along those lines came from Parnas [20], who wanted correctness assertions in module interfaces. More recently, Beugnard, Jézéquel, Plouzeau, and Watkins [2] proposed that components should come with four levels of interface descriptions: 1. syntactic aspects (type systems, i-o dependencies); 2. behavioral guarantees (weak or strong logical assertions); 3. concurrency guarantees and warnings; 4. quality of service statements. They refer to such rich interfaces as contracts. This paper focuses on behavioral contracts. The usefulness of contracts depends on their enforcement. Unless contracts are verified or monitored, there is no assurance that the software works properly. Hence, it is paramount that contracts have a precise meaning and that the language implementation enforces the meaning of contracts. In particular, contract violations must be pinpointed as precisely as possible, because blaming the wrong component manufacturer (a person, a department, or an external supplier) or providing the wrong explanation for a failure may cause economic damage. Object-oriented programming languages (OOPL) have strongly embraced the notion of components and behavioral contracts. For example, Meyer’s [17] Eiffel explicitly incorporates the notion of “programming by contract.” More precisely, an Eiffel class plays the role of a component. A programmer can express behavioral contracts via logical assertions about the calling context, the return of a method, and as invariants across calls. Eiffel supports these contracts with a run-time monitoring system. If a pre-condition fails, Eiffel blames the caller of the method; if a post-condition fails, it assigns the blame to the method. Recently, several research teams have adapted Eiffel’s notion of “programming by contract” to Java [5, 8, 10, 15]. Unfortunately, unlike contract monitoring tools for procedural languages, none of those for object-oriented languages do not live up to their promises. As it turns out, catching contract violations and assigning blame properly poses subtle problems. More concretely, we believe that the problems of existing tools are due to a lack of foundational work on contracts and contract violations. There is little work on the semantics of behavioral contracts, contract monitoring, and contract violations. In this paper, we present the idea of behavioral contracts for object-oriented languages in general and for Java in particular. Although we study this problem in the context of Java, the issues that we address are common to any component mechanism that includes objects. Then we discuss how the existing contract enforcement tools fail to deal with contracts properly. Finally, we formulate a challenge for the foundational software engineering community, namely, the design of a semantics of contracts and contract violations for behavioral contracts. In the next section we briefly introduce four Java contract tools. In section 3 we look at concrete examples for which the tools fail and analyze why. In section 4, we formulate the contract enforcement problem and discuss several options concerning its solution. Section 5 discusses related work and the last section is a brief summary. 2 Behavioral Contracts in the OOP World In Java, it is natural to argue that behavioral contracts should be associated with Java interfaces. Following Eiffel’s early example [17], contracts should be logical assertions—boolean expressions involving the program’s variables—about methods and classes. More concretely, a programmer can specify pre-conditions and post-conditions on a method.1 Also following Eiffel’s example, the run-time system should monitor the logical assertions about classes and methods. In particular, it should signal the failure of a pre-condition or post-condition. In Eiffel’s case, the system blames the caller of a method when a pre-condition fails, and it blames the method itself when the post-condition fails. Useful contracts are not necessarily complete descriptions of a method’s behavior. Requiring completeness would demand much more logic training for programmers than currently available. Instead, useful contracts often specify just some essential aspects of a method’s behavior. Consider the following example: . . . String get file name(); // The method interactively queries the user for the // name of an existing file. // @post: System.file exists(@ret) The informal constraint expresses the complete behavior of the method in English. The quasi-formal post-condition specifies that the result of the method is a string for which the file exists predicate succeeds. Here is a second example: . . . void click button(Button btn); // The method simulates a user click on the button btn // It is only feasible to click on a button when the button’s // top-level window is visible and has the focus. // @pre: f Window w = System.get top level focus window(); // w.contains(btn) // && btn.is enabled() // && btn.is shown() g 1 Eiffel also allows programmers to specify invariants. We ignore invariants here, because dealing with preand post-conditions poses a sufficiently rich set of problems.
منابع مشابه
Behavioral Interface Contracts for Java (Rice University CS TR00-366)
Programs should consist of off-the-shelf, interchangeable, black-box components that are produced by a network of independent software companies. These components should not only come with type signatures but also with contracts that describe other aspects of their behavior. One way to express contracts is to state preand postconditions for externally visible functions. These preand post-condit...
متن کاملAspects in a Prototype-Based Environment
Most of the existing aspect-oriented technologies are founded on a class-based object-oriented language. A whole other paradigm of objectoriented programming is thus ignored: prototype-based programming. In this paper we explore the impact of the differences of prototype-based and class-based programming on the design of crosscut languages and the implementation of weaving. Crosscut languages f...
متن کاملIntroducing Ontologically Founded Roles in Object Oriented Programming: PowerJava
In this paper we introduce a new view on roles in Object Oriented programming languages. Our notion is based on an ontological analysis of social roles and attributes to roles the following properties: first, a role is always associated not only to an object instance playing the role, but also to another object instance which constitutes the context of the role and which we call institution. Se...
متن کاملAnalysing and Optimizing Strongly Typed Object-oriented Languages: A Generic Approach and its Application to Oberon-2
Object-oriented programming is going to replace the imperative programming paradigm as the state-of-the-art paradigm for large industrial software projects. The beneets ooered, however, come at the price of intricate new problems for optimizing compilers. In contrast to the imperative paradigm, where abstract interpretation is well-established as a uniform and theoretically well-founded framewo...
متن کاملذخیره در منابع من
با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید
عنوان ژورنال:
دوره شماره
صفحات -
تاریخ انتشار 2001